package wave;

import java.util.*;

public class WaveActs implements WaveEXEConstants {
//---------------------------
/**
* public static Vector add(Vector op1, Vector op2) throws NumberFormatException
* First element in op1, op2 are String which are the TYPE of the elements start from second position.
* Here the TYPE must be TYPE_INT.
* Otherwise, null is returned.
*/
	public static Vector add(Vector op1, Vector op2) {
		Vector o1, o2, sum = new Vector();
		int i;

		op1 = convertToInt( op1 );
		op2 = convertToInt( op2 );

		if(op1.size() > op2.size()) {
			o1 = op1;
			o2 = op2;
		} else {
			o1 = op2;
			o2 = op1;
		}

		for( i = 0; i < o2.size(); i++) {
			sum.addElement( new Integer( ( (Integer)o1.elementAt(i) ).intValue() + ( (Integer)o2.elementAt(i) ).intValue() ) );
		}
		for( ; i < o1.size(); i++) {
			sum.addElement( o1.elementAt(i) );
		}

		return sum;
	}
//---------------------------
// return a new copy, can be used independently
	public static Vector convertToInt(Vector op) {
		Object obj;
		Vector v = new Vector();

		for( int i = 0; i < op.size(); i++ ) {
			obj = op.elementAt(i);
			if( obj instanceof Integer ) {
				v.addElement( new Integer( ( (Integer)obj ).intValue() )  );
			} else {
				v.addElement( new Integer( 0 ) );
			}
		}

		return v;
	}
//---------------------------
	public static Vector negate(Vector op) {
		Vector ret = convertToInt( op );

		for( int i = 0; i < ret.size(); i++ )
			ret.setElementAt( new Integer( -( (Integer)ret.elementAt(i) ).intValue() ) , i);

		return ret;
	}
//---------------------------
	public static Vector subtract(Vector op1, Vector op2) {
		Vector o2 = negate( op2 );

		return add(op1, o2);
	}
//---------------------------
// Operations of vectors with scalars (e.g. Fx=1;2;3.Fx*2.T=Fx would show 2;4;6 on the screen)
	public static Vector multiply(Vector op1, Vector op2) {
		Vector o1, o2, mul = new Vector();
		int i;

		op1 = convertToInt( op1 );
		op2 = convertToInt( op2 );
		
		if(op1.size() > op2.size()) {
			o1 = op1;
			o2 = op2;
		} else {
			o1 = op2;
			o2 = op1;
		}

		if( o2.size() == 1 ){
			int i2 = ((Integer)o2.elementAt(0) ).intValue();
			for( i = 0; i < o1.size(); i++) {
				mul.addElement( new Integer( ( (Integer)o1.elementAt(i) ).intValue() * i2 ) );
			}
		} else {
			for( i = 0; i < o2.size(); i++) {
				mul.addElement( new Integer( ( (Integer)o1.elementAt(i) ).intValue() * ( (Integer)o2.elementAt(i) ).intValue() ) );
			}
			for( ; i < o1.size(); i++) {
				mul.addElement( new Integer( 0 ) );
			}
		}

		return mul;
	}
//---------------------------
// Operations of vectors with scalars (e.g. Fx=1;2;3.Fx/2.T=Fx would show 0;1;1 on the screen) ??
	public static Vector divide(Vector op1, Vector op2) {
		Vector o1, o2, div = new Vector();
		int i, val;

		o1 = convertToInt( op1 );
		o2 = convertToInt( op2 );
		
		if( o2.size() == 1 ){
			int i2 = ((Integer)o2.elementAt(0) ).intValue();
			if( i2 == 0 ) throw new ArithmeticException( FALSE ); //Divided by Zero

			for( i = 0; i < o1.size(); i++) {
				div.addElement( new Integer( ( (Integer)o1.elementAt(i) ).intValue() / i2 ) );
			}
		} else {
			if(o1.size() > o2.size()) {
				throw new ArithmeticException( FALSE ); //Divided by Zero
			}

			for( i = 0; i < o1.size(); i++) {
				val = ( (Integer)o2.elementAt(i) ).intValue();
				if( val == 0 ) throw new ArithmeticException( FALSE ); //Divided by Zero

				div.addElement( new Integer( ( (Integer)o1.elementAt(i) ).intValue() / val ) );
			}
		}

		return div;
	}
//---------------------------
	public static boolean equals(Vector op1, Vector op2){
		int i;
		Object o1, o2;

		if(op1.size() != op2.size())
			return false;

		for( i = 0; i < op1.size(); i++) {
			o1 = op1.elementAt(i);
			o2 = op2.elementAt(i);
			if( o1 instanceof String) {
				if ( o2 instanceof String ) {
					if( ((String)o1).equals((String)o2) )
						continue;
					else
						return false;
				} else if ( o2 instanceof Integer ) {
					if( ((String)o1).equals(((Integer)o2).toString()) )
						continue;
					else
						return false;
				} else {
					System.out.println("Equal-1: type is not scaler.");
					return false;
				}
			} else if ( o1 instanceof Integer ) {
				if ( o2 instanceof String ) {
					if( ((String)o2).equals(((Integer)o1).toString()) )
						continue;
					else
						return false;
				} else if ( o2 instanceof Integer ) {
					if( ((Integer)o1).equals( (Integer)o2 ) )
						continue;
					else
						return false;
				} else {
					System.out.println("Equal-2: type is not scaler.");
					return false;
				}
			} else{
				System.out.println("Equal-2: type is not scaler.");
				return false;
			}
		}

		return true;
	}
//---------------------------
	public static boolean notEqual(Vector op1, Vector op2){
		return (!equals(op1, op2));
	}
//---------------------------
	public static boolean lessEqual(Vector op1, Vector op2){
		int i;
		Object o1, o2;

		if( op1.size() > op2.size() )
			return false;

		for( i = 0; i < op1.size(); i++) {
			o1 = op1.elementAt(i);
			o2 = op2.elementAt(i);
			if( isNum(o1.toString())) {
				if ( isNum(o2.toString()) ) {
					if( Integer.parseInt(o1.toString())<= Integer.parseInt(o2.toString()) )
						continue;
					else
						return false;
				} else if ( o2 instanceof String ) {
					if( ((Integer)o1).toString().compareTo(((String)o2)) <= 0 )
						continue;
					else
						return false;
				} else {
System.out.println("LessEqual-1: type is not scaler.");
					return false;
				}
			} else if ( o1 instanceof String ) {
				if ( o2 instanceof String ) {
					if( ((String)o1).compareTo((String)o2) <= 0 )
						continue;
					else
						return false;
				} else if ( o2 instanceof Integer ) {
					if( ((String)o1).compareTo(((Integer)o2).toString())<=0) // TODOIR: Check
						continue;
					else
						return false;
				} else {
System.out.println("Equal-2: type is not scaler.");
					return false;
				}
			} else{
System.out.println("Equal-2: type is not scaler.");
				return false;
			}
		}

		return true;
	}
//---------------------------
	public static boolean lessThan(Vector op1, Vector op2){
		int i;
		Object o1, o2;

		if( op1.size() > op2.size() )
			return false;

		for( i = 0; i < op1.size(); i++) {
			o1 = op1.elementAt(i);
			o2 = op2.elementAt(i);
			if( isNum(o1.toString())) {
				if ( isNum(o2.toString()) ) {
					if( Integer.parseInt(o1.toString())< Integer.parseInt(o2.toString()) )
						continue;
					else
						return false;
				} else if ( o2 instanceof String ) {
					if( ((Integer)o1).toString().compareTo(((String)o2)) < 0 )
						continue;
					else
						return false;
				} else {
System.out.println("LessEqual-1: type is not scaler.");
					return false;
				}
			} else if ( o1 instanceof String ) {
				if ( o2 instanceof String ) {
					if( ((String)o1).compareTo((String)o2) < 0 )
						continue;
					else
						return false;
				} else if ( o2 instanceof Integer ) {
					if( ((String)o1).compareTo(((Integer)o2).toString())<0) // TODOIR: Check
						continue;
					else
						return false;
				} else {
System.out.println("Equal-2: type is not scaler.");
					return false;
				}
			} else{
System.out.println("Equal-2: type is not scaler.");
				return false;
			}
		}

		return true;
	}
//---------------------------
	//element position does not matter. This is a set operation.
	//TRUE: if any element of left operand belong to the right operans
	//FALSE: otherwise.
	public static boolean contain(Vector op1, Vector op2){
		int i, j;
		Object o1, o2;

		if( op1.size() > op2.size() )
			return false;

		for( i = 0; i < op1.size(); i++) {
			o1 = op1.elementAt(i);
			for(j = 0; j < op2.size(); j++) {
				o2 = op2.elementAt(j);
				if( o1 instanceof String) {
					if ( o2 instanceof String ) {
						if( ((String)o1).equals((String)o2) )
							break;
						else
							continue;
					} else if ( o2 instanceof Integer ) {
						if( ((String)o1).equals(((Integer)o2).toString()) )
							break;
						else
							continue;
					} else {
	System.out.println("Equal-1: type is not scaler.");
						return false;
					}
				} else if ( o1 instanceof Integer ) {
					if ( o2 instanceof String ) {
						if( ((String)o2).equals(((Integer)o1).toString()) )
							break;
						else
							continue;
					} else if ( o2 instanceof Integer ) {
						if( ((Integer)o1).equals( (Integer)o2 ) )
							break;
						else
							continue;
					} else {
	System.out.println("Equal-2: type is not scaler.");
						return false;
					}
				} else{
	System.out.println("Equal-2: type is not scaler.");
					return false;
				}
			}
			if( j >= op2.size() )
				return false;
		}

		return true;
	}
//---------------------------
//merge the vector on the left into a single string using right dilimiters
//if right if NONE or empty, merely concatenate all elements.
//if & appears on right, it seperate the result string into vectors.
	public static Vector concat(Vector op1, Vector op2){
		Vector v = new Vector(op1);
        v.addAll(op2);        
        return v;
	}

    public static Vector join(Vector op1, Vector op2) {
        int i, j;
		Vector v = new Vector();
		String s = "";
		Object o1, o2;

		if( op2.size() == 0 ) {
            // There are no delimiters, so break the whole left vector into a string
			for( i = 0; i < op1.size(); i++ ) {
				o1 = op1.elementAt(i);
				s += o1.toString();
			}
			v.addElement( s );
			return v;
		}

		j = 0;
		for( i = 0; i < op1.size(); i++, j++) {
			o1 = op1.elementAt(i);
			if ( j >= op2.size() ) j = 0;
			o2 = op2.elementAt(j);
			if( o2.toString().equals("&") ) {
				v.addElement( s );
				s = "";
			} else {
                if (i == op1.size()-1) s += o1.toString();
                else
				s += o1.toString() + o2.toString();
			}
		}

		if ( v.size() == 0 || !s.equals("") ) {
			v.addElement( s );
		}

		return v;
    }
//---------------------------
// |
//split each element in the vector on the left into more elements using right dilimiters
//if right if NONE or empty, merely split all elements into single characters.
//right side is in round robin fashion
	public static Vector split(Vector op1, Vector op2){
		int i, j, k, m;
		Vector v = new Vector();
		String s = "", s1;
		Object o1, o2;

		if( op2.size() == 0 ) {
			for( i = 0; i < op1.size(); i++ ) {
				o1 = op1.elementAt(i);
				s = o1.toString();
				for( k = 0; k < s.length(); k++ ) {
					v.addElement( s.substring(k, k+1) );
				}
			}
			return v;
		}

		j = k = 0; 
		for( i = 0; i < op1.size(); i++, j++) {
			s = op1.elementAt(i).toString();
            if (s.startsWith("`")) s = s.substring(1, s.length()-1);
            System.out.println(s);
			if ( j >= op2.size() ) j = 0;
			s1 = op2.elementAt(j).toString();
            if (s1.startsWith("`")) s1 = s1.substring(1,s1.length()-1);
			while( (m = s.indexOf(s1, k)) != -1 ) {
				v.addElement( s.substring(k, m) );
				k = m + s1.length();
				if ( k >= s.length() ) break;
			}
			if ( k < s.length() ) {
				v.addElement( s.substring(k, s.length()) );
			}
		}

		return v;
	}
//---------------------------
// links#nodes
	public static void hop(Vector links, Vector nodes, String tail){
	}
//---------------------------
	public static Vector decodeFrontal( byte[] buf, int start, int end ) {
		Vector v = new Vector();
		int j = start, i = start +1;
		for(; i <= end; i++) {
			if(buf[i] == END_OF_ELEMENT){
				if(buf[j] == INTEGER_ELEMENT){
					Integer in;
					try{
						in = new Integer(Integer.parseInt(new String(buf, j+1, i - j -1) ));
					} catch (NumberFormatException ne) {
						in = new Integer(0);
					}
					v.addElement( in );
					j = i + 1;
				} else { //string item
					v.addElement( new String(buf, j+1, i - j -1) );
				}
			}
		}

		return v;
	}
//---------------------------
	public static String encodeFrontal( Vector v ) {
		String s = "";
		for( int i = 0; i < v.size(); i++) {
			Object o = v.elementAt(i);
			if( o instanceof String ) {
				s += String.valueOf( (char)STRING_ELEMENT ) + (String)o
						+ String.valueOf( (char)END_OF_ELEMENT);
			} else if( o instanceof Integer ) {
				s += String.valueOf( (char)INTEGER_ELEMENT ) + ((Integer)o).toString()
						+ String.valueOf( (char)END_OF_ELEMENT);
			}
		}

		return s;
	}
//---------------------------
//---------------------------
//---------------------------
//---------------------------
//---------------------------
//---------------------------
//---------------------------
//---------------------------
//---------------------------
//---------------------------
//---------------------------
//---------------------------
//---------------------------
/**
* Input type must be TYPE_INT or TYPE_STRING
* Output: out1, out2
*/
	public static void unifyType(Vector op1, Vector op2, Vector out1, Vector out2) {
		String type1, type2;
		int i;
		out1.removeAllElements();
		out2.removeAllElements();

		type1 = (String)op1.elementAt(0);
		type2 = (String)op2.elementAt(0);

		if(  type1.equals( type2 ) ) {
			for ( i = 0; i < op1.size(); i++ ) {
				out1.addElement( op1.elementAt(i) );
			}
			for ( i = 0; i < op2.size(); i++ ) {
				out2.addElement( op2.elementAt(i) );
			}
		} else if ( type1.equals( TYPE_STRING ) ) {
			for ( i = 0; i < op1.size(); i++ ) {
				out1.addElement( op1.elementAt(i) );
			}
			out2.addElement( TYPE_STRING );
			for( i = 1; i < op2.size(); i++ ) {
				out2.addElement( ( (Integer)op2.elementAt(i) ).toString() );
			}
		} else {
			for ( i = 0; i < op2.size(); i++ ) {
				out2.addElement( op2.elementAt(i) );
			}
			out1.addElement( TYPE_STRING );
			for( i = 1; i < op1.size(); i++ ) {
				out1.addElement( ( (Integer)op1.elementAt(i) ).toString() );
			}
		}
	}

    public static boolean isNum (String str) {
        try{
            Integer.parseInt(str);
        } catch(NumberFormatException nfe) {
            return false;
        }
        return true;
    }
}
